﻿package test;

import java.security.Key;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;

/**
 * ********************************************************
 * 
 * @ClassName: EcbTest
 * @Description: MAC 工具类，采用ECB算法
 * @author xh
 * @date 2013-1-10 上午10:57:53
 ******************************************************* 
 */
public class EcbTripdes {
	public byte[] IV = new byte[8];
	private final String keyStr = "F24831854E6D3DE0F1C6CE474F15B94F";

	public byte byteXOR(byte src, byte src1) {
		return (byte) ((src & 0xFF) ^ (src1 & 0xFF));
	}

	public byte[] bytesXOR(byte[] src, byte[] src1) {
		int length = src.length;
		if (length != src1.length) {
			return null;
		}
		byte[] result = new byte[length];
		for (int i = 0; i < length; i++) {
			result[i] = byteXOR(src[i], src1[i]);
		}
		return result;
	}

	/**
	 * ********************************************************
	 * 
	 * @Title: clacMac
	 * @Description: 
	 *               Mac计算,数据不为8的倍数，需要补0，将数据8个字节进行异或，再将异或的结果与下一个8个字节异或，一直到最后，将异或后的数据进行DES计算
	 * @param key
	 * @param Input
	 * @return
	 * @date 2013-1-10 上午10:58:38
	 *       *******************************************************
	 */
	public byte[] clacMac(byte[] key, byte[] Input) {
		try {
			int length = Input.length;
			int x = length % 8;
			int addLen = 0;
			if (x != 0) {
				addLen = 8 - length % 8;
			}
			String bzero = "";
			for (int i = 0; i < addLen; i++) {
				bzero += "0";
			}

			int pos = 0;
			byte[] data = new byte[length + addLen];
			System.arraycopy(Input, 0, data, 0, length);
			System.arraycopy(new byte[addLen], 0, data, Input.length, addLen);
			byte[] oper1 = new byte[8];
			System.arraycopy(data, pos, oper1, 0, 8);
			pos += 8;
			for (int i = 1; i < data.length / 8; i++) {
				byte[] oper2 = new byte[8];
				System.arraycopy(data, pos, oper2, 0, 8);
				byte[] t = bytesXOR(oper1, oper2);
				oper1 = t;
				pos += 8;
			}
			byte[] buff = encrypt(oper1, key);
			// 取8个长度字节
			byte[] retBuf = new byte[8];
			System.arraycopy(buff, 0, retBuf, 0, 8);
			return retBuf;
		} catch (Exception e) {
			return null;
		}
	}

	public byte[] encrypt(byte[] data, byte[] key) {
		byte newkey[] = new byte[24];
		try {
			System.arraycopy(key, 0, newkey, 0, key.length);
			System.arraycopy(key, 0, newkey, 16, 8);

			Key k = toKey(newkey);
			Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
			cipher.init(Cipher.ENCRYPT_MODE, k);
			return cipher.doFinal(data);
		} catch (Exception e) {
			return null;
		}
	}

	public SecretKey toKey(byte[] key) throws Exception {
		KeySpec dks = new DESedeKeySpec(key); // 这里改为了 DESedeKeySpec
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
		return keyFactory.generateSecret(dks);
	}

	public byte[] hexStr2Bytes(String src) {
		int m = 0, n = 0;
		int l = src.length() / 2;
		byte[] ret = new byte[l];
		for (int i = 0; i < l; i++) {
			m = i * 2 + 1;
			n = m + 1;
			ret[i] = uniteBytes(src.substring(i * 2, m), src.substring(m, n));
		}
		return ret;
	}

	private byte uniteBytes(String src0, String src1) {
		byte b0 = Byte.decode("0x" + src0).byteValue();
		b0 = (byte) (b0 << 4);
		byte b1 = Byte.decode("0x" + src1).byteValue();
		byte ret = (byte) (b0 | b1);
		return ret;
	}

	public String byte2HexStr(byte[] b) {
		String hs = "";
		String stmp = "";
		for (int n = 0; n < b.length; n++) {
			stmp = (Integer.toHexString(b[n] & 0XFF));
			if (stmp.length() == 1)
				hs = hs + "0" + stmp;
			else
				hs = hs + stmp;
		}
		return hs.toUpperCase();
	}

	// public static void main(String[] args) throws Exception {
	// EcbTripdes tdes = new EcbTripdes();
	// byte[] buff =
	// "1000184112990000456313100000000086111111111100012012050616472388888888880005"
	// .getBytes();
	//
	// System.out.println("buff len:" + buff.length);
	// byte[] key = tdes.hexStr2Bytes("F24831854E6D3DE0F1C6CE474F15B94F");
	// String encryptedData = tdes.byte2HexStr(tdes.clacMac(key, buff));
	// System.out.println(encryptedData);
	//
	// // byte[] key = tdes.hexStr2Bytes("F24831854E6D3DE0F1C6CE474F15B94F");
	// // byte[] data = tdes.hexStr2Bytes("065259B3EEE8CF99");
	// // System.out.println(tdes.byte2HexStr(tdes.encrypt(data, key)));
	// }

	/**
	 * 加密数据
	 */
	public String entryptedData(String str) {
		byte[] key = hexStr2Bytes(keyStr);
		return byte2HexStr(clacMac(key, str.getBytes()));
	}
}
